#include <gtest/gtest.h>
#include "viml/object.h"
#include "viml/types.h"
#include "viml/garbage_collector.h"

using namespace viml;

class ObjectModelTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 每个测试前的设置
    }

    void TearDown() override {
        // 每个测试后的清理
    }
};

// Object基类测试
TEST_F(ObjectModelTest, ObjectBasics) {
    // 测试对象头部的创建和类型设置
    auto obj = std::make_unique<Object>(ObjectHeader::Type::STRING);

    EXPECT_EQ(obj->header().type, ObjectHeader::Type::STRING);
    EXPECT_FALSE(obj->is_string());
    EXPECT_TRUE(obj->is_list());
    EXPECT_EQ(obj->get_ref_count(), 1);
    EXPECT_TRUE(obj->is_valid_object());
}

TEST_F(ObjectModelTest, ReferenceCounting) {
    // 测试引用计数的基本操作
    auto obj = std::make_unique<Object>(ObjectHeader::Type::LIST);

    EXPECT_EQ(obj->get_ref_count(), 1);

    obj->ref();
    EXPECT_EQ(obj->get_ref_count(), 2);

    obj->unref();
    EXPECT_EQ(obj->get_ref_count(), 1);

    obj->unref();
    // 注意：这里不应该delete测试，因为测试框架会处理
}

TEST_F(ObjectModelTest, MarkAndSweep) {
    // 测试标记和清理功能
    auto obj = std::make_unique<Object>(ObjectHeader::Type::DICT);

    EXPECT_FALSE(obj->is_marked());

    obj->mark();
    EXPECT_TRUE(obj->is_marked());

    obj->unmark();
    EXPECT_FALSE(obj->is_marked());
}

// StringObject测试
TEST_F(ObjectModelTest, StringObjectCreation) {
    auto str_obj1 = std::make_unique<StringObject>("Hello, World!")
    auto str_obj2 = std::make_unique<StringObject>(std::string("VimL"));
    auto str_obj3 = std::make_unique<StringObject>("Test");

    EXPECT_EQ(str_obj1->data(), "Hello, World!");
    EXPECT_EQ(str_obj2->data(), "VimL");
    EXPECT_EQ(str_obj3->data(), "Test");

    EXPECT_TRUE(str_obj1->is_string());
    EXPECT_TRUE(str_obj2->is_string());
    EXPECT_TRUE(str_obj3->is_string());
}

TEST_F(ObjectModelTest, StringObjectOperations) {
    auto str1 = std::make_unique<StringObject>("Hello");
    auto str2 = std::make_unique<StringObject>("World");

    // 测试字符串连接
    auto concat = str1->concatenate(*str2);
    EXPECT_EQ(concat->data(), "HelloWorld");

    // 测试大小写转换
    auto upper = str1->to_upper();
    EXPECT_EQ(upper->data(), "HELLO");

    auto lower = str1->to_lower();
    EXPECT_EQ(lower->data(), "hello");

    // 测试查找操作
    EXPECT_EQ(str1->find('o'), 4);
    EXPECT_EQ(str1->find('x'), std::string::npos);

    // 测试包含操作
    EXPECT_TRUE(str1->contains('o'));
    EXPECT_FALSE(str1->contains('x'));

    // 测试子字符串
    auto substr = str1->substring(1, 3);
    EXPECT_EQ(substr->data(), "ell");
}

TEST_F(ObjectModelTest, StringObjectTrimAndSplit) {
    auto str = std::make_unique<StringObject>("  Hello World  ");

    // 测试trim
    auto trimmed = str->trim();
    EXPECT_EQ(trimmed->data(), "Hello World");

    // 测试分割
    auto words = str->split(" ");
    EXPECT_EQ(words->size(), 2);
    EXPECT_EQ(words->get(0).to_string(), "Hello");
    EXPECT_EQ(words->get(1).to_string(), "World");
}

// ListObject测试
TEST_F(ObjectModelTest, ListObjectCreation) {
    auto list1 = std::make_unique<ListObject>();
    auto list2 = std::make_unique<ListObject>();

    EXPECT_TRUE(list1->empty());
    EXPECT_EQ(list1->size(), 0);

    EXPECT_TRUE(list2->empty());
    EXPECT_EQ(list2->size(), 0);

    // 测试初始化列表
    std::vector<Value> elems;
    elems.push_back(Value(1));
    elems.push_back(Value(2));
    elems.push_back(Value(3));

    auto list3 = std::make_unique<ListObject>({Value(1), Value(2), Value(3)});
    EXPECT_EQ(list3->size(), 3);
    EXPECT_EQ(list3->get(0), Value(1));
    EXPECT_EQ(list3->get(1), Value(2));
    EXPECT_EQ(list3->get(2), Value(3));
}

TEST_F(ObjectModelTest, ListObjectOperations) {
    auto list = std::make_unique<ListObject>({Value(1), Value(2), Value(3)});

    // 测试访问操作
    EXPECT_EQ(list->get(0), Value(1));
    EXPECT_EQ(list->get(2), Value(3));

    // 测试越界访问
    EXPECT_THROW(list->get(10), std::out_of_range);

    // 测试修改操作
    list->set(0, Value(42));
    EXPECT_EQ(list->get(0), Value(42));

    // 测试插入和删除
    list->insert(1, Value(99));
    EXPECT_EQ(list->size(), 4);
    EXPECT_EQ(list->get(1), Value(99));

    list->erase(1);
    EXPECT_EQ(list->size(), 3);
    EXPECT_EQ(list->get(1), Value(2));

    // 测试查找操作
    EXPECT_EQ(list->find(Value(42)), 0);
    EXPECT_EQ(list->find(Value(100)), std::numeric_limits<size_t>::max());
    EXPECT_TRUE(list->contains(Value(2)));
    EXPECT_FALSE(list->contains(Value(99)));
}

TEST_F(ObjectModelTest, ListObjectSliceAndExtend) {
    auto list1 = std::make_unique<ListObject>({Value(1), Value(2), Value(3), Value(4), Value(5)});
    auto list2 = std::make_unique<ListObject>({Value(6), Value(7)});

    // 测试切片操作
    auto slice = list1->slice(1, 3);
    EXPECT_EQ(slice->size(), 3);
    EXPECT_EQ(slice->get(0), Value(2));
    EXPECT_EQ(slice->get(1), Value(3));
    EXPECT_EQ(slice->get(2), Value(4));

    // 测试扩展
    list1->extend(*list2);
    EXPECT_EQ(list1->size(), 7);
    EXPECT_EQ(list1->get(5), Value(6));
    EXPECT_EQ(list1->get(6), Value(7));
}

TEST_F(ObjectModelTest, ListObjectSortingAndReversing) {
    auto list = std::make_unique<ListObject>({Value(3), Value(1), Value(4), Value(2), Value(5)});

    // 测试排序
    list->sort();
    EXPECT_EQ(list->get(0), Value(1));
    EXPECT_EQ(list->get(1), Value(2));
    EXPECT_EQ(list->get(2), Value(3));
    EXPECT_EQ(list->get(3), Value(4));
    EXPECT_EQ(list->get(4), Value(5));

    // 测试反转
    list->reverse();
    EXPECT_EQ(list->get(0), Value(5));
    EXPECT_EQ(list->get(1), Value(4));
    EXPECT_EQ(list->get(2), Value(3));
    EXPECT_EQ(list->get(3), Value(2));
    EXPECT_EQ(list->get(4), Value(1));
}

// DictObject测试
TEST_F(ObjectModelTest, DictObjectCreation) {
    auto dict1 = std::make_unique<DictObject>();
    auto dict2 = std::make_unique<DictObject>();

    EXPECT_TRUE(dict1->empty());
    EXPECT_EQ(dict1->size(), 0);

    EXPECT_TRUE(dict2->empty());
    EXPECT_EQ(dict2->size(), 0);
}

TEST_F(ObjectModelTest, DictObjectBasicOperations) {
    auto dict = std::make_unique<DictObject>();

    Value key1 = std::make_unique<StringObject>("key1");
    Value key2 = std::make_unique<StringObject>("key2");
    Value value1 = Value(42);
    Value value2 = Value(100);

    // 测试插入操作
    dict->set(key1, value1);
    dict->set(key2, value2);

    EXPECT_EQ(dict->size(), 2);
    EXPECT_EQ(dict->get(key1), value1);
    EXPECT_EQ(dict->get(key2), value2);

    // 测试访问不存在的键
    auto key3 = std::make_unique<StringObject>("nonexistent");
    EXPECT_TRUE(dict->get(key3).is_nil());

    // 测试包含检查
    EXPECT_TRUE(dict->contains(key1));
    EXPECT_TRUE(dict->contains(key2));
    EXPECT_FALSE(dict->contains(key3));

    // 测试覆盖插入
    dict->set(key1, Value(99));
    EXPECT_EQ(dict->get(key1), Value(99));

    // 测试删除操作
    bool removed = dict->erase(key2);
    EXPECT_TRUE(removed);
    EXPECT_EQ(dict->size(), 1);
    EXPECT_EQ(dict->contains(key2), false);
    EXPECT_FALSE(dict->contains(key1)); // key1应该还存在
}

TEST_F(ObjectModelTest, DictObjectMergeAndUpdate) {
    auto dict1 = std::make_unique<DictObject>();
    auto dict2 = std::make_unique<DictObject>();

    // 设置两个字典
    Value key1 = std::make_unique<StringObject>("key1");
    Value key2 = std::make_unique<StringObject>("key2");

    dict1->set(key1, Value(100));
    dict1->set(key2, Value(200));

    dict2->set(key2, Value(300));
    dict2->set(key3, Value(400));

    // 测试合并操作
    dict1->merge(*dict2);
    EXPECT_EQ(dict1->size(), 3);
    EXPECT_EQ(dict1->get(key1), Value(100));
    EXPECT_EQ(dict1->get(key2), Value(300));
    EXPECT_EQ(dict1->get(std::make_unique<StringObject>("key3")), Value(400));

    // 测试更新操作
    dict1->update(*dict2);
    EXPECT_EQ(dict1->size(), 3); // 大小不变，因为key2存在
    EXPECT_EQ(dict1->get(key2), Value(300)); // 值不变，因为已存在

    // 插入新键
    dict1->set(std::make_unique<StringObject>("new_key"), Value(500));
    dict2->update(*dict1);
    EXPECT_EQ(dict2->size(), 4);
    EXPECT_EQ(dict2->get(std::make_unique<StringObject>("new_key")), Value(500));
}

// 垃圾回收器测试
TEST_F(ObjectModelTest, GarbageCollectorBasic) {
    auto gc = GarbageCollector(GCType::MARK_AND_SWEEP);

    EXPECT_TRUE(gc.is_enabled());
    EXPECT_EQ(gc.get_type(), GCType::MARK_AND_SWEEP);

    auto stats = gc.get_stats();
    EXPECT_EQ(stats.total_objects, 0);
    EXPECT_EQ(stats.collected_objects, 0);
    EXPECT_EQ(stats.collection_cycles, 0);

    gc.reset_stats();
    auto stats_after_reset = gc.get_stats();
    EXPECT_EQ(stats_after_reset.total_objects, 0);
    EXPECT_EQ(stats_after_reset.collected_objects, 0);
    EXPECT_EQ(stats_after_reset.collection_cycles, 0);
}

TEST_F(ObjectModelTest, GarbageCollectorAddAndCollect) {
    auto gc = GarbageCollector(GCType::MARK_AND_SWEEP);

    // 创建一些对象
    auto obj1 = std::make_unique<Object>(ObjectHeader::Type::STRING);
    auto obj2 = std::make_unique<Object>(ObjectHeader::Type::LIST);
    auto obj3 = std::make_unique<Object>(ObjectHeader::Type::DICT);

    // 添加到GC管理
    gc.add_object(obj1.get());
    gc.add_object(obj2.get());
    gc.add_object(obj3.get());

    auto stats_before = gc.get_stats_copy();
    EXPECT_EQ(stats_before.total_objects, 3);

    // 执行垃圾回收
    gc.collect();

    auto stats_after = gc.get_stats_copy();
    EXPECT_EQ(stats_after.total_objects, 0); // 所有对象都被回收
    EXPECT_GT(stats_after.collected_objects, 0);
    EXPECT_GT(stats_after.collection_cycles, 0);
}

// 内存管理和性能测试
TEST_F(ObjectModelTest, MemoryManagement) {
    // 测试智能指针的行为
    {
        auto obj = std::make_unique<Object>(ObjectHeader::Type::STRING);
        {
            ObjPtr<Object> ptr1(obj.get());
            EXPECT_EQ(obj->get_ref_count(), 2);

            {
                ObjPtr<Object> ptr2(ptr1);
                EXPECT_EQ(obj->get_ref_count(), 3);
            }
            // ptr2析构时，引用计数应该减到2
            EXPECT_EQ(obj->get_ref_count(), 2);
        }
        // ptr1析构时，引用计数应该减到1
        EXPECT_EQ(obj->get_ref_count(), 1);
    }
}

TEST_F(ObjectModelTest, ObjectValidation) {
    // 测试对象魔数
    auto obj = std::make_unique<Object>(ObjectHeader::Type::STRING);
    EXPECT_TRUE(obj->is_valid_object());

    // 测试对象大小限制
    auto str_obj = std::make_unique<StringObject>(std::string(1000, 'a'));
    EXPECT_TRUE(str_obj->is_valid_length());

    auto long_str_obj = std::make_unique<StringObject>(std::string(2000, 'b'));
    EXPECT_FALSE(long_str_obj->is_valid_length()); // 超过限制
}

// 边界条件和错误处理测试
TEST_F(ObjectModelTest, EdgeCasesAndErrorHandling) {
    auto list = std::make_unique<ListObject>();

    // 测试空列表的操作
    EXPECT_THROW(list->get(0), std::out_of_range);
    EXPECT_THROW(list->erase(0), std::out_of_range);

    // 测试字符串边界
    auto empty_str = std::make_unique<StringObject>("");
    EXPECT_EQ(empty_str->size(), 0);
    EXPECT_EQ(empty_str->find('a'), std::string::npos);

    // 测试字典边界
    auto dict = std::make_unique<DictObject>();
    Value key = std::make_unique<StringObject>("test");
    EXPECT_TRUE(dict->get(key).is_nil()); // 不存在的键

    // 设置空键
    dict->set(std::make_unique<StringObject>(""), Value(42));
    // 注意：空字符串键的处理应该在具体实现中定义
}